collection.js ➔ ???   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 11
Bugs 0 Features 0
Metric Value
c 11
b 0
f 0
nc 1
nop 4
dl 0
loc 7
ccs 4
cts 4
cp 1
cc 1
crap 1
rs 9.4285

1 Function

Rating   Name   Duplication   Size   Complexity  
A collection.js ➔ ... ➔ ??? 0 1 1
1
import {looseEqual, pick} from '../utils'
2
import BaseSyncer from './base'
3
4
/**
5
 * Collection syncer used for multiple items
6
 */
7
export default class CollectionSyncer extends BaseSyncer {
8
9
	/**
10
	 * Create a syncer for feathers
11
	 *
12
	 * @param Vue
13
	 * @param vm
14
	 * @param path
15
	 * @param settings
16
	 */
17
	constructor(Vue, vm, path, settings) {
18 20
		super(Vue, vm, path, settings)
19
20 20
		this._matcher = () => true // For without query
21 20
		this._createMatcher = Vue.$syncer.matcher
22 20
		this._filterParser = Vue.$syncer.filter
23
	}
24
25
	/**
26
	 * Handle new item creations from feathers
27
	 *
28
	 * @param item
29
	 */
30
	onItemCreated(item) {
31 4
		if (this._itemMatches(item)) {
32 3
			item = this._transformPerQuery(item)
33 3
			this._set(item[this._id], item)
34
		}
35
	}
36
37
	/**
38
	 * Handle item updates from feathers
39
	 *
40
	 * @param item
41
	 */
42
	onItemUpdated(item) {
43 13
		if (this._itemMatches(item)) {
44 8
			item = this._transformPerQuery(item)
45 8
			this._set(item[this._id], item)
46 5
		} else if (item[this._id] in this.state) {
47 2
			this._remove(item[this._id])
48
		}
49
	}
50
51
	/**
52
	 * Handle item removals from feathers
53
	 *
54
	 * @param item
55
	 */
56
	onItemRemoved(item) {
57 3
		if (item[this._id] in this.state) {
58 2
			this._remove(item[this._id])
59
		}
60
	}
61
62
	/**
63
	 * Bind watchers for computed values
64
	 *
65
	 * @private
66
	 */
67
	_bindComputedValues() {
68 20
		if ('query' in this.settings) {
69 9
			this.filters.query = null
70
71
			// When new value is found
72 9
			const callback = function (newVal) {
73
				// Avoid re-querying if it's the same
74 12
				if (looseEqual(this.filters.query, newVal)) {
75 1
					this.filters.query = newVal
76 1
					return
77
				}
78
79 11
				this.filters.query = newVal
80 11
				if (newVal === null) {
81 1
					this.filters.queryParsed = null
82
				} else {
83 10
					this.filters.queryParsed = this._filterParser(newVal)
84
				}
85
86
				// Clear state (if query is now null it makes sure everything's reset)
87 11
				this.state = this._initialState()
88 11
				this._matcher = () => false
89
90
				// Default return nothing
91 11
				let returning = false
92 11
				if (this.filters.query !== null) {
93 10
					this._matcher = this._createMatcher(this.filters.query)
94 10
					returning = this._loadNewState()
95
				}
96
97 11
				if ('hook' in callback) {
98 9
					callback.hook(returning)
99 9
					delete callback.hook
100
				}
101
			}
102
103 9
			return new Promise(resolve => {
104 9
				callback.hook = resolve
105
106 9
				this.unwatchers.query = this.vm.$watch(this.settings.query, callback.bind(this), {immediate: true})
107
			})
108
		}
109
110 11
		return this._loadNewState()
111
	}
112
113
	/**
114
	 * Initial data for item syncer
115
	 *
116
	 * @returns {*}
117
	 * @private
118
	 */
119
	_initialState() {
120 74
		return {}
121
	}
122
123
	/**
124
	 * Checks if item matches what's in collection
125
	 *
126
	 * @param item
127
	 * @returns {boolean}
128
	 * @private
129
	 */
130
	_itemMatches(item) {
131 17
		return this._matcher(item)
132
	}
133
134
	/**
135
	 * Load the requested state
136
	 *
137
	 * @returns {Promise.<T>}
138
	 * @private
139
	 */
140
	_loadState() {
141 24
		const params = {}
142
143 24
		if (this.filters.query) {
144 10
			params.query = this.filters.query
145
		}
146
147 24
		return this.service.find(params).then(items => {
148 24
			if (this.vm === null) {
149
				// Destroy has been called during loading
150 1
				return items
151
			}
152
153 23
			this.state = this._initialState()
154
155
			// If the service is paginated
156 23
			if (Array.isArray(items) === false && typeof items.data !== 'undefined') {
157 1
				items = items.data
158
			}
159
160 23
			items.forEach(item => {
161 38
				this._set(item[this._id], item)
162
			})
163 23
			this._newStateLoaded()
164
165 23
			return items
166
		}).catch(this._handleStateLoadingError.bind(this))
167
	}
168
169
	/**
170
	 * Set current item
171
	 *
172
	 * @param key
173
	 * @param item
174
	 * @private
175
	 */
176
	_set(key, item) {
177 49
		this.Vue.set(this.state, key, item)
178
	}
179
180
	/**
181
	 * Remove current item
182
	 *
183
	 * @private
184
	 */
185
	_remove(key) {
186 4
		this.Vue.delete(this.state, key)
187
	}
188
189
	/**
190
	 * Transform item using current filter's rules
191
	 *
192
	 * @param item
193
	 * @private
194
	 */
195
	_transformPerQuery(item) {
196 11
		if (this.filters.queryParsed) {
197 8
			const filters = this.filters.queryParsed.filters
198 8
			if (filters.$select) {
199 3
				item = pick(item, ...filters.$select)
200
			}
201
		}
202 11
		return item
203
	}
204
}
205